﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BusinessModel;
using EntityDataModel;
using System.ComponentModel;
using System.Data.Objects.DataClasses;
using BaseUtilities;
using BusinessModel.Reports;

namespace Controller.DataProvider
{
    public class ReportPro
    {
        public ReportPro()
        {
        }

        #region Public Methods
        //----------------------------------------
        public IList<ProductBusinessRpt> ToModel(IList<Tbl_Product> pLstProduct)
        {
            IList<ProductBusinessRpt> result = pLstProduct.Select(p => new ProductBusinessRpt()
            {
                ProductId = p.Id,
                TypeId = p.TypeId,
                ProductCode = p.Code,
                ProductName = p.Name,
                TypeCode = p.Tbl_ProductType.Code,
                TypeName = p.Tbl_ProductType.Name,
                Quantity = p.Quantity,
                BuyAmount = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value),
                SaleAmount = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value * sd.SalePriceUnit.Value),
                ConsignAmount = p.Tbl_BuyOrderDetail.Where(bd => bd.IsConsign.HasValue && bd.IsConsign.Value).Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value)
            }).ToList<ProductBusinessRpt>();
            return result;
        }
        //----------------------------------------
        private ProductBusinessRpt Mtd_SelectProduct(Tbl_Product pTbl_Product)
        {
            int iQuantity = 0;
            int iTypeId = 0;
            ProductBusinessRpt result = new ProductBusinessRpt()
                     {
                         ProductId = pTbl_Product.Id,
                         TypeId = pTbl_Product.TypeId,
                         ProductCode = pTbl_Product.Code,
                         ProductName = pTbl_Product.Name,
                         TypeCode = pTbl_Product.Tbl_ProductType.Code,
                         TypeName = pTbl_Product.Tbl_ProductType.Name,
                         Quantity = pTbl_Product.Quantity,
                         Amount = pTbl_Product.Tbl_BuyOrderDetail.Where(bd => !bd.IsConsign.HasValue || !bd.IsConsign.Value).OrderByDescending(pd => pd.BuyDate).TakeWhile((pd) =>
                             {
                                 bool isTake = iQuantity < pd.Tbl_Product.Quantity;
                                 if (isTake)
                                 {
                                     iQuantity += pd.Quantity.Value;
                                     if (iQuantity >= pd.Tbl_Product.Quantity)
                                         iTypeId = pd.Id;
                                 }
                                 return isTake;
                             })
                         .Sum(bd =>
                             {
                                 int iAmount = bd.BuyPriceUnit.Value;
                                 if (iTypeId == bd.Id)
                                     iAmount *= bd.Quantity.Value - (iQuantity - pTbl_Product.Quantity.Value);
                                 else
                                     iAmount *= bd.Quantity.Value;
                                 return iAmount;
                             }),
                         //BuyAmount = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value),
                         //SaleAmount = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value * sd.SalePriceUnit.Value),
                         ConsignAmount = pTbl_Product.Tbl_BuyOrderDetail.Where(bd => bd.IsConsign.HasValue && bd.IsConsign.Value).Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value)
                     };
            return result;
        }
        //----------------------------------------
        public ResultModel GetsProductInStock()
        {
            IList<ProductBusinessRpt> result;
            using (ManageStoreEntities entities = new ManageStoreEntities())
            {
                result = entities.Tbl_Product.Select<Tbl_Product, ProductBusinessRpt>(new Func<Tbl_Product, ProductBusinessRpt>((Tbl_Product p) =>
                    {
                        int iQuantity = 0;
                        int iTypeId = 0;
                        ProductBusinessRpt oProductBusinessRpt = new ProductBusinessRpt()
                                 {
                                     ProductId = p.Id,
                                     TypeId = p.TypeId,
                                     ProductCode = p.Code,
                                     ProductName = p.Name,
                                     TypeCode = p.Tbl_ProductType.Code,
                                     TypeName = p.Tbl_ProductType.Name,
                                     Quantity = p.Quantity,
                                     Amount = p.Tbl_BuyOrderDetail.OrderByDescending(pd => pd.BuyDate).TakeWhile((pd) =>
                                         {
                                             bool isTake = iQuantity < pd.Tbl_Product.Quantity;
                                             if (isTake)
                                             {
                                                 iQuantity += pd.Quantity.Value;
                                                 if (iQuantity >= pd.Tbl_Product.Quantity)
                                                     iTypeId = pd.Id;
                                             }
                                             return isTake;
                                         })
                                     .Sum(bd =>
                                         {
                                             int iAmount = bd.BuyPriceUnit.Value;
                                             if (iTypeId == bd.Id)
                                                 iAmount *= bd.Quantity.Value - (iQuantity - p.Quantity.Value);
                                             else
                                                 iAmount *= bd.Quantity.Value;
                                             return iAmount;
                                         }),
                                     //BuyAmount = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value),
                                     //SaleAmount = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value * sd.SalePriceUnit.Value),
                                     ConsignAmount = p.Tbl_BuyOrderDetail.Where(bd => bd.IsConsign.HasValue && bd.IsConsign.Value).Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value)
                                 };
                        return oProductBusinessRpt;
                    }
                    )).ToList();
            }
            return new ResultModel(result);
        }
        //----------------------------------------
        public ResultModel GetsProductInStock(int pIndex, int pSize)
        {
            IList<ProductBusinessRpt> result;
            using (ManageStoreEntities entities = new ManageStoreEntities())
            {
                result = entities.Tbl_Product.Select<Tbl_Product, ProductBusinessRpt>(new Func<Tbl_Product, ProductBusinessRpt>((Tbl_Product p) =>
                {
                    int iQuantity = 0;
                    int iTypeId = 0;
                    ProductBusinessRpt oProductBusinessRpt = new ProductBusinessRpt()
                    {
                        ProductId = p.Id,
                        TypeId = p.TypeId,
                        ProductCode = p.Code,
                        ProductName = p.Name,
                        TypeCode = p.Tbl_ProductType.Code,
                        TypeName = p.Tbl_ProductType.Name,
                        Quantity = p.Quantity,
                        Amount = p.Tbl_BuyOrderDetail.OrderByDescending(pd => pd.BuyDate).TakeWhile((pd) =>
                        {
                            bool isTake = iQuantity < pd.Tbl_Product.Quantity;
                            if (isTake)
                            {
                                iQuantity += pd.Quantity.Value;
                                if (iQuantity >= pd.Tbl_Product.Quantity)
                                    iTypeId = pd.Id;
                            }
                            return isTake;
                        })
                        .Sum(bd =>
                        {
                            int iAmount = bd.BuyPriceUnit.Value;
                            if (iTypeId == bd.Id)
                                iAmount *= bd.Quantity.Value - (iQuantity - p.Quantity.Value);
                            else
                                iAmount *= bd.Quantity.Value;
                            return iAmount;
                        }),
                        //BuyAmount = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value),
                        //SaleAmount = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value * sd.SalePriceUnit.Value),
                        ConsignAmount = p.Tbl_BuyOrderDetail.Where(bd => bd.IsConsign.HasValue && bd.IsConsign.Value).Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value)
                    };
                    return oProductBusinessRpt;
                }
                    )).OrderBy(p => p.TypeName).Skip(pIndex).Take(pSize).ToList();
            }
            return new ResultModel(result);
        }
        //----------------------------------------
        public ResultModel GetsProductInStockBuy()
        {
            IList<ProductBusinessRpt> result;
            using (ManageStoreEntities entities = new ManageStoreEntities())
            {
                result = entities.Tbl_Product.Select(p => new ProductBusinessRpt()
                {
                    ProductId = p.Id,
                    TypeId = p.TypeId,
                    ProductCode = p.Code,
                    ProductName = p.Name,
                    TypeCode = p.Tbl_ProductType.Code,
                    TypeName = p.Tbl_ProductType.Name,
                    Quantity = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value),
                    Amount = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value),
                    //BuyAmount = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value),
                    //SaleAmount = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value * sd.SalePriceUnit.Value),
                    //ConsignAmount = p.Tbl_BuyOrderDetail.Where(bd => bd.IsConsign.HasValue && bd.IsConsign.Value).Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value)
                }).ToList();
            }
            return new ResultModel(result);
        }
        //----------------------------------------
        public ResultModel GetsProductInStockSale()
        {
            IList<ProductBusinessRpt> result;
            using (ManageStoreEntities entities = new ManageStoreEntities())
            {
                result = entities.Tbl_Product.Where(p => p.Tbl_SaleOrderDetail.Count > 0).Select(p => new ProductBusinessRpt()
                {
                    ProductId = p.Id,
                    TypeId = p.TypeId,
                    ProductCode = p.Code,
                    ProductName = p.Name,
                    TypeCode = p.Tbl_ProductType.Code,
                    TypeName = p.Tbl_ProductType.Name,
                    Quantity = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value),
                    Amount = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value * sd.SalePriceUnit.Value),
                    //BuyAmount = p.Tbl_BuyOrderDetail.Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value),
                    //SaleAmount = p.Tbl_SaleOrderDetail.Sum(sd => sd.Quantity.Value * sd.SalePriceUnit.Value),
                    //ConsignAmount = p.Tbl_BuyOrderDetail.Where(bd => bd.IsConsign.HasValue && bd.IsConsign.Value).Sum(bd => bd.Quantity.Value * bd.BuyPriceUnit.Value)
                }).ToList();
            }
            return new ResultModel(result);
        }
        //----------------------------------------
        public ResultModel GetProductCount()
        {
            int result = 0;
            using (ManageStoreEntities entities = new ManageStoreEntities())
            {
                result = entities.Tbl_Product.Count();
            }
            return new ResultModel(result);
        }
        //----------------------------------------
        public ResultModel GetProductSaleCount()
        {
            int result = 0;
            using (ManageStoreEntities entities = new ManageStoreEntities())
            {
                result = entities.Tbl_Product.Where(p => p.Tbl_SaleOrderDetail.Count > 0) .Count();
            }
            return new ResultModel(result);
        }
        #endregion Public Methods
    }
}
